/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2018-2019 Hechzh Property

   
*/
#include "include/susan.h"
#include "dird/dird.h"
#include "ndmp/smc.h"

namespace directordaemon {
/**
 * calculate the element address for given slotnumber and slot_type
 */
/* clang-format off */
slot_number_t GetElementAddressBySusanSlotNumber(
    smc_element_address_assignment* smc_elem_aa,
    slot_type_t slot_type,
    slot_number_t slotnumber)
{
  slot_number_t calculated_slot;

  switch (slot_type) {
    case slot_type_t::kSlotTypeStorage:
      if ((slotnumber > smc_elem_aa->se_count) ||
          !IsSlotNumberValid(slotnumber)) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = slotnumber
                        + smc_elem_aa->se_addr
                        - 1;  // normal slots count start from 1
      }
      break;
    case slot_type_t::kSlotTypeImport:
      if ((slotnumber < (smc_elem_aa->se_count + 1)) ||
          (slotnumber > (smc_elem_aa->se_count + smc_elem_aa->iee_count + 1))) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = slotnumber
                        - smc_elem_aa->se_count // i/e slots follow after normal slots
                        + smc_elem_aa->iee_addr
                        - 1;                    // normal slots count start from 1
      }
      break;
    case slot_type_t::kSlotTypePicker:
      if ((slotnumber == kInvalidSlotNumber) ||
          slotnumber > (smc_elem_aa->mte_count - 1)) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = slotnumber
                        + smc_elem_aa->mte_addr;
      }
      break;
    case slot_type_t::kSlotTypeDrive:
      if ((slotnumber > (smc_elem_aa->dte_count) - 1) ||
          (slotnumber == kInvalidSlotNumber)) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = slotnumber
                        + smc_elem_aa->dte_addr;
      }
      break;
    default:
    case slot_type_t::kSlotTypeUnknown:
      calculated_slot = kInvalidSlotNumber;
      break;
  }
  return calculated_slot;
}

/**
 * calculate the slotnumber for element address and slot_type
 */
slot_number_t GetSusanSlotNumberByElementAddress(
    smc_element_address_assignment* smc_elem_aa,
    slot_type_t slot_type,
    slot_number_t element_addr)
{
  slot_number_t calculated_slot;

  switch (slot_type) {
    case slot_type_t::kSlotTypeStorage:
      if (element_addr < smc_elem_aa->se_addr ||
          (element_addr > smc_elem_aa->se_addr + smc_elem_aa->se_count - 1)) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = element_addr
                        - smc_elem_aa->se_addr
                        + 1;  // slots count start from 1
      }
      break;
    case slot_type_t::kSlotTypeImport:
      if ((element_addr < smc_elem_aa->iee_addr) ||
          (element_addr > smc_elem_aa->iee_addr + smc_elem_aa->iee_count - 1)) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = element_addr
                        + smc_elem_aa->se_count  // i/e slots follow after normal slots
                        - smc_elem_aa->iee_addr
                        + 1;                     // slots count start from 1
      }
      break;
    case slot_type_t::kSlotTypeDrive:
      if ((element_addr < smc_elem_aa->dte_addr) ||
          (element_addr > smc_elem_aa->dte_addr + smc_elem_aa->dte_count - 1)) {
        calculated_slot = kInvalidSlotNumber;
      } else {
        calculated_slot = element_addr
                        - smc_elem_aa->dte_addr;
      }
      break;
    case slot_type_t::kSlotTypePicker:
      calculated_slot = element_addr
                      - smc_elem_aa->mte_addr;
      break;
    default:
    case slot_type_t::kSlotTypeUnknown:
      calculated_slot = kInvalidSlotNumber;
      break;
  }
  return calculated_slot;
}
/* clang-format on */

} /* namespace directordaemon */
